/**
 * js 客户端缓存处理
 * 缓存解构为: {key: value}
 */
class _Cache {
    constructor(key) {
        this._key = key || "Global";
        this._value = {};
        this._scope = "_global_";
        this._scope_ = "_global_";
        this._relatedKey = "parentId";
        this._localCacheKeyName = "LocalCache_";
    }

    get key() {
        return this._localCacheKeyName + this._key;
    }

    get value() {
        return this._value;
    }

    get scope() {
        return this._scope;
    }

    /**
     * 判断简单类型的值是否为空
     * @param {any} value
     */
    hasValue(value) {
        if (value !== null && value !== '' && value !== undefined && typeof value !== 'undefined') {
            return true;
        }

        return false;
    }

    /**
     * 加载缓存
     */
    load() {
        if (this.hasValue(this.key)) {
            this._value = JSON.parse(localStorage.getItem(this.key)) || {};
        }
    }

    /**
     * 按键设置并刷新缓存的值
     * @param {string} key 键
     * @param {any} value 缓存值
     * @param {string} scope 缓存范围
     */
    set(key, value, scope) {
        this._scope = scope || this._scope_;

        if (this.hasValue(key) && this.hasValue(value)) {
            if (!this.hasValue(this.value)) {
                this._value = {};
            }

            if (this.hasValue(this.scope)) {
                if (!this.value[this.scope]) {
                    this.value[this.scope] = {};
                }

                this.value[this.scope][key] = value;
            }
        }

        localStorage.setItem(this.key, JSON.stringify(this.value));
    }

    /**
     * get by key(键) 按键查找缓存内容, 数组类型的值的增强功能请使用数组的扩展方法进行二次查询
     * @param {string} key 键, 过滤缓存值的键
     * @param {string} scope 缓存范围
     */
    get(key, scope) {
        this._scope = scope || this._scope_;

        if (this.hasValue(key) && this.hasValue(this.scope) && this.hasValue(this.value[this.scope])) {
            return this.value[this.scope][key];
        }
    }

    /**
     * 获取键缓存个数
     * @param {string} scope 缓存范围
     */
    getKeyCount(scope) {
        this._scope = scope || this._scope_;

        var count = 0;
        if (this.hasValue(this.scope) && this.hasValue(this.value[this.scope])) {
            for (var key in this.value[this.scope]) {
                if (this.hasValue(key)) {
                    count++;
                }
            }
        }

        return count;
    }

    /**
     * 移除一个缓存的键值对
     * @param {any} key 缓存的键
     * @param {string} scope 缓存范围
     */
    remove(key, scope) {
        this._scope = scope || this._scope_;

        if (this.hasValue(key) && this.hasValue(this.scope) && this.hasValue(this.value[this.scope])) {
            delete this.value[this.scope][key];

            if (this.getKeyCount(this.scope) === 0) {
                delete this.value[this.scope];
            }

            this.set();
        }
    }
}

/**
 * 提供以 Page 作为缓存主键, 及当前 url 作为默认范围的客户端缓存
 * 在缓存键值对的基础上, 在最上层在提供一级范围进行缓存隔离
 * 即缓存解构为: {scope: {key: value}}
 */
class PageCache extends _Cache {
    constructor() {
        super("Page");
        this._scope = "/";
    }

    get key() {
        return this._localCacheKeyName + "Page";
    }

    /**
     * 重载的 set 方法, 接受 scope 参数
     * @param {any} key
     * @param {any} value
     * @param {any} scope
     */
    set(key, value, scope) {
        this._scope = scope || location.href;
        super.set(key, value);
    }

    /**
     * 重载的 get 方法, 接受 scope 参数
     * @param {any} key
     * @param {any} scope
     */
    get(key, scope) {
        this._scope = scope || location.href;
        return super.get(key);
    }

    /**
     * 重载的 remove 方法, 接受 scope 参数
     * @param {any} key
     * @param {any} scope
     */
    remove(key, scope) {
        this._scope = scope || location.href;
        super.remove(key);
    }
}

/**
 * 本地缓存, 预定义的 global 和 page 缓存 
 */
var localCache = new class LocalCache {
    constructor() {
        this.debug = false;
        this.global = new _Cache();
        this.page = new PageCache();
    }

    load() {
        return Promise.resolve()
            .then(() => this.global.load())
            .then(() => this.page.load())
            .then(() => {
                if (this.debug) {
                    console.log("缓存加载完毕!");
                }
            });
    }
}();